"""
用户数据访问层
封装用户模型的数据库操作
"""
from typing import List, Optional, Dict, Any, Tuple
from tortoise.expressions import Q
from tortoise.functions import Count

from apps.auth.models.user import User



class UserRepository:
    """用户数据访问层"""
    
    @staticmethod
    async def create(user_data: Dict[str, Any]) -> User:
        """
        创建用户
        :param user_data: 用户数据字典
        :return: 创建的用户实例
        """
        user = await User.create(**user_data)
        return user
    
    @staticmethod
    async def get_by_id(user_id: int) -> Optional[User]:
        """
        通过ID获取用户
        :param user_id: 用户ID
        :return: 用户实例或None
        """
        return await User.get_by_id(user_id)
    
    @staticmethod
    async def get_by_username(username: str) -> Optional[User]:
        """
        通过用户名获取用户
        :param username: 用户名
        :return: 用户实例或None
        """
        return await User.get_by_username(username)
    
    @staticmethod
    async def get_by_email(email: str) -> Optional[User]:
        """
        通过邮箱获取用户
        :param email: 邮箱
        :return: 用户实例或None
        """
        return await User.get_by_email(email)
    
    @staticmethod
    async def list_users(
        page: int = 1, 
        page_size: int = 10,
        search: Optional[str] = None,
        status: Optional[int] = None,
        role: Optional[str] = None,
        order_by: str = "-created_at"
    ) -> Tuple[List[User], int]:
        """
        获取用户列表
        :param page: 页码
        :param page_size: 每页大小
        :param search: 搜索关键词(用户名/邮箱/全名)
        :param status: 用户状态过滤
        :param role: 用户角色过滤
        :param order_by: 排序字段
        :return: 用户列表和总数
        """
        # 构建基本查询
        query = User.filter(is_deleted=False)
        
        # 应用过滤条件
        if search:
            query = query.filter(
                Q(username__icontains=search) | 
                Q(email__icontains=search) | 
                Q(full_name__icontains=search)
            )
        
        if status:
            query = query.filter(status=status)
            
        if role:
            # query = query.filter(user_roles__role__name=role)
            # query = query.filter(user_roles__role__slug=role)
            query = query.filter(user_roles__role=role)

        # 计算总数
        total = await query.count()
        
        # 获取分页数据
        users = await query.order_by(order_by).offset((page - 1) * page_size).limit(page_size).all()
        
        return users, total
    
    @staticmethod
    async def update(user: User, update_data: Dict[str, Any]) -> User:
        """
        更新用户信息
        :param user: 用户实例
        :param update_data: 更新的字段数据
        :return: 更新后的用户实例
        """
        # 过滤掉None值，只更新提供了的字段
        valid_updates = {k: v for k, v in update_data.items() if v is not None}
        
        # 更新用户实例字段
        for key, value in valid_updates.items():
            setattr(user, key, value)
            
        # 保存到数据库
        await user.save()
        
        return user
    
    @staticmethod
    async def update_whole(user: User, update_data: Dict[str, Any]) -> User:
        """
        全部更新用户信息
        :param user: 用户实例
        :param update_data: 完整的更新数据
        :return: 更新后的用户实例
        """
        # 更新所有字段，包括未提供的字段(设为默认值)
        for key, value in update_data.items():
            setattr(user, key, value)
            
        await user.save()
        
        return user
    
    @staticmethod
    async def delete(user: User) -> None:
        """
        软删除用户
        :param user: 用户实例
        """
        await user.soft_delete()
    
    @staticmethod
    async def hard_delete(user: User) -> None:
        """
        硬删除用户(永久删除)
        :param user: 用户实例
        """
        await user.delete()
    
    @staticmethod
    async def exists_by_id(user_id: int) -> bool:
        """
        检查用户ID是否存在
        :param user_id: 用户ID
        :return: 是否存在
        """
        return await User.exists_by_id(user_id)
    
    @staticmethod
    async def exists_by_username(username: str) -> bool:
        """
        检查用户名是否存在
        :param username: 用户名
        :return: 是否存在
        """
        return await User.filter(username=username, is_deleted=False).exists()
    
    @staticmethod
    async def exists_by_email(email: str) -> bool:
        """
        检查邮箱是否存在
        :param email: 邮箱
        :return: 是否存在
        """
        return await User.filter(email=email, is_deleted=False).exists()
